<template>
    <div class="tag-nav">
        <div class="close-con">
            <Dropdown transfer @on-click="handleTagsOption" style="margin-top:7px;">
                <Button size="small" type="text">
                    <Icon :size="18" type="ios-close-circle-outline" />
                </Button>
                <DropdownMenu slot="list">
                    <DropdownItem name="close-all">关闭所有</DropdownItem>
                    <DropdownItem name="close-others">关闭其他</DropdownItem>
                </DropdownMenu>
            </Dropdown>
        </div>
        <ul v-show="visible" :style="{left: contextMenuLeft + 'px', top: contextMenuTop + 'px'}" class="contextmenu">
            <li v-for="(item, key) of menuList" @click="handleTagsOption(key)" :key="key">{{ item }}</li>
        </ul>
        <div class="btn-con left-btn">
            <Button type="text" @click="handleScroll(240)">
                <Icon :size="18" type="ios-arrow-back" />
            </Button>

        </div>
        <div class="btn-con right-btn">
            <Button type="text" @click="handleScroll(-240)">
                <Icon :size="18" type="ios-arrow-forward" />
            </Button>
        </div>
        <div class="scroll-outer" ref="scrollOuter" @DOMMouseScroll="handleScrollDelta" @mousewheel="handleScrollDelta">
            <div ref="scrollBody" class="scroll-body" :style="{left: tagBodyLeft + 'px'}">
                <transition-group name="taglist-moving-animation">
                    <Tag
                        style="font-size:14px;"
                        type="dot"
                        v-for="(item, index) in pageTagsList"
                        ref="tagsPageOpened"
                        :key="`tag-nav-${index}`"
                        :name="item.name"
                        @on-close="closePage"
                        @click.native="linkTo(item)"
                        :closable="item.name==='home'?false:true"
                        :color="item.children?(item.children[0].name===currentPageName?'primary':'default'):(item.name===currentPageName?'primary':'default')"
                        @contextmenu.prevent.native="contextMenu(item, $event)"
                    >{{ item.meta.title }}
                    </Tag>
                </transition-group>
            </div>
        </div>
    </div>
</template>

<script lang="ts">
import Util from '@/lib/util';
import {Component, Vue, Prop, Emit, Watch} from 'vue-property-decorator';
import AbpBase from '@/lib/abpbase';

@Component({
    components: {},
})
export default class TagNav extends AbpBase {
    name: string = 'TagNav';

    @Prop({type: Array}) pageTagsList: any[];
    @Prop({
        type: Function, default: () => {
            return true;
        },
    }) beforePush: (item: any) => {};

    currentPageName?: string;
    tagBodyLeft: number = 0;
    refsTag: any | any[] = [];
    tagsCount: number = 1;
    outerPadding: number = 4;
    contextMenuLeft: number = 0;
    contextMenuTop: number = 0;
    visible: boolean = false;
    menuList: any = {
        others: '关闭其他',
        all: '关闭所有',
    };

    constructor() {
        super();
    }

    get title() {
        return this.$store.state.app.currentTitle;
    }

    get tagsList() {
        return this.$store.state.app.pageOpenedList;
    }


    handleScrollDelta(e) {
        var type = e.type;
        let delta = 0;
        if (type === 'DOMMouseScroll' || type === 'mousewheel') {
            delta = (e.wheelDelta) ? e.wheelDelta : -(e.detail || 0) * 40;
        }
        this.handleScroll(delta);
    }

    handleScroll(offset) {
        const outerWidth = (this.$refs.scrollOuter as any).offsetWidth;
        const bodyWidth = (this.$refs.scrollBody as any).offsetWidth;
        if (offset > 0) {
            this.tagBodyLeft = Math.min(0, this.tagBodyLeft + offset);
        } else {
            if (outerWidth < bodyWidth) {
                if (this.tagBodyLeft < -(bodyWidth - outerWidth)) {

                } else {
                    this.tagBodyLeft = Math.max(this.tagBodyLeft + offset, outerWidth - bodyWidth);
                }
            } else {
                this.tagBodyLeft = 0;
            }
        }
    }

    handleTagsOption(type: any) {
        if (type.includes('all')) {

            this.$store.commit('app/clearAllTags');
            this.$router.push({
                name: 'home',
            });
        } else if (type.includes('others')) {

            this.$store.commit('app/clearOtherTags', this);
        }
        this.tagBodyLeft = 0;
    }

    closePage(event: any, name: string) {
        this.$store.commit('app/removeTag', name);
        this.$store.commit('app/closePage', name);
        let pageOpenedList = this.$store.state.app.pageOpenedList;
        localStorage.pageOpenedList = JSON.stringify(pageOpenedList);
        if (this.currentPageName === name) {
            let lastPageName = '';
            if (pageOpenedList.length > 1) {
                lastPageName = pageOpenedList[1].name;
            } else {
                lastPageName = pageOpenedList[0].name;
            }
            this.$router.push({
                name: lastPageName,
            });
        }
    }

    linkTo(item: any) {
        let routerObj: any = {};
        routerObj.name = item.name;
        if (item.arg) {
            routerObj.params = item.arg;
        }
        if (item.query) {
            routerObj.query = item.query;
        }
        if (this.beforePush(item)) {
            this.$router.push(routerObj);
        }
    }

    moveToView(tag) {
        const outerWidth = (this.$refs.scrollOuter as any).offsetWidth;
        const bodyWidth = (this.$refs.scrollBody as any).offsetWidth;
        if (bodyWidth < outerWidth) {
            this.tagBodyLeft = 0;
        } else if (tag.offsetLeft < -this.tagBodyLeft) {

            this.tagBodyLeft = -tag.offsetLeft + this.outerPadding;
        } else if (tag.offsetLeft > -this.tagBodyLeft && tag.offsetLeft + tag.offsetWidth < -this.tagBodyLeft + outerWidth) {

            this.tagBodyLeft = Math.min(0, outerWidth - tag.offsetWidth - tag.offsetLeft - this.outerPadding);
        } else {

            this.tagBodyLeft = -(tag.offsetLeft - (outerWidth - this.outerPadding - tag.offsetWidth));
        }
    }

    contextMenu(item, e) {
        if (item.name === 'home') {
            return;
        }
        this.visible = true;
        const offsetLeft = this.$el.getBoundingClientRect().left;
        this.contextMenuLeft = e.clientX - offsetLeft + 10;
        this.contextMenuTop = e.clientY - 64;
    }

    closeMenu() {
        this.visible = false;
    }

    @Watch('$route')
    routeChange(to: any) {
        this.currentPageName = to.name;
        this.$nextTick(() => {
            (this.refsTag as any[]).forEach((item, index) => {
                if (this.$route.name === item.name) {
                    let tag = this.refsTag[index].$el;
                    this.moveToView(tag);
                }
            });
        });
        this.tagsCount = this.tagsList.length;
    }

    @Watch('visible')
    visibleChange(value) {
        if (value) {
            document.body.addEventListener('click', this.closeMenu);
        } else {
            document.body.removeEventListener('click', this.closeMenu);
        }
    }

    created() {
        this.currentPageName = this.$route.name;
    }

    mounted() {
        this.refsTag = this.$refs.tagsPageOpened;
        setTimeout(() => {
            (this.refsTag as any[]).forEach((item, index) => {
                if (this.$route.name === item.name) {
                    let tag = this.refsTag[index].$el;
                    this.moveToView(tag);
                }
            });
        }, 1);
        this.tagsCount = this.tagsList.length;
    }
}

</script>

<style lang="less" scoped>
@import './styles/tag-nav.less';
</style>
